using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using admin.application.Dtos;
using admin.application.Common;
using admin.core.Common;
using admin.core.Entities.App;
using admin.core.Repositories;
using System.Data;
using Dapper;

namespace admin.application.Services
{
    public class AppUserService : IAppUserService
    {
        private readonly IRepository<AppUser> _userRepo;
        private readonly IRepository<AppRole> _roleRepo;
        private readonly IDbConnection _dbConnection;

        public AppUserService(IRepository<AppUser> userRepo, IRepository<AppRole> roleRepo, IDbConnection dbConnection)
        {
            _userRepo = userRepo;
            _roleRepo = roleRepo;
            _dbConnection = dbConnection;
        }

        public async Task<IEnumerable<UserDto>> GetAllAsync()
        {
            var users = await _userRepo.GetAllAsync();
            return users.OrderBy(u => u.CreatedAt).Select(u => new UserDto
            {
                Id = u.Id,
                Username = u.UserName,
                IsEnabled = u.IsActived,
                CreatedAt = u.CreatedAt
            });
        }

        public async Task<UserDto> GetByIdAsync(Guid id)
        {
            var u = await _userRepo.GetByIdAsync(id) ?? throw new Exception("用户不存在");
            return new UserDto
            {
                Id = u.Id,
                Username = u.UserName,
                IsEnabled = u.IsActived,
                CreatedAt = u.CreatedAt
            };
        }

        public async Task<PaginationResult<UserDto>> GetPagedAsync(PaginationRequest request)
        {
            var pagedResult = await _userRepo.GetPagedAsync(request);
            var userDtos = pagedResult.Items
                .OrderBy(u => u.CreatedAt)
                .Select(u => new UserDto
                {
                    Id = u.Id,
                    Username = u.UserName,
                    IsEnabled = u.IsActived,
                    CreatedAt = u.CreatedAt
                }).ToList();

            return new PaginationResult<UserDto>(userDtos, pagedResult.TotalCount, pagedResult.PageNumber, pagedResult.PageSize);
        }

        public async Task CreateAsync(CreateUserDto dto)
        {
            var salt = Guid.NewGuid().ToString("N");
            var pwdHash = HashPassword(dto.Password, salt);
            var user = new AppUser { UserName = dto.Username, PassWord = pwdHash, Salt = salt };
            user = await _userRepo.AddAsync(user);

            // 自动分配默认角色"用户"
            var roles = await _roleRepo.GetAllAsync();
            var defaultRole = roles.FirstOrDefault(r => r.RoleName == "用户");
            if (defaultRole == null)
            {
                defaultRole = new AppRole
                {
                    RoleName = "用户",
                    DataScope = "Self",
                    Code = "USER",
                    IsActived = true,
                    IsDeleted = false,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow,
                    CreatedBy = user.Id,
                    UpdatedBy = user.Id
                };
                defaultRole = await _roleRepo.AddAsync(defaultRole);
            }
            // 直接插入中间表，保证数据库有绑定关系
            var sql = "INSERT INTO \"AppRoleAppUser\" (\"UsersId\", \"RolesId\") VALUES (@UserId, @RoleId) ON CONFLICT DO NOTHING;";
            await _dbConnection.ExecuteAsync(sql, new { UserId = user.Id, RoleId = defaultRole.Id });
        }

        public async Task UpdateAsync(Guid id, UpdateUserDto dto)
        {
            var user = await _userRepo.GetByIdAsync(id) ?? throw new Exception("用户不存在");
            await _userRepo.UpdateAsync(user);
        }

        public async Task DeleteAsync(Guid id)
        {
            var user = await _userRepo.GetByIdAsync(id);
            if (user == null) throw new NotFoundException("用户不存在");
            await _userRepo.DeleteAsync(user);
        }

        public async Task EnableAsync(Guid id)
        {
            var user = await _userRepo.GetByIdAsync(id);
            if (user == null) throw new NotFoundException("用户不存在");
            user.IsActived = true;
            await _userRepo.UpdateAsync(user);
        }

        public async Task DisableAsync(Guid id)
        {
            var user = await _userRepo.GetByIdAsync(id);
            if (user == null) throw new NotFoundException("用户不存在");
            user.IsActived = false;
            await _userRepo.UpdateAsync(user);
        }

        public async Task AssignRoleAsync(Guid userId, Guid roleId)
        {
            // 检查用户和角色是否存在
            var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
            var role = await _roleRepo.GetByIdAsync(roleId) ?? throw new Exception("角色不存在");

            // 直接插入中间表
            var sql = "INSERT INTO \"AppRoleAppUser\" (\"UsersId\", \"RolesId\") VALUES (@UserId, @RoleId) ON CONFLICT DO NOTHING;";
            await _dbConnection.ExecuteAsync(sql, new { UserId = userId, RoleId = roleId });
        }

        public async Task RemoveRoleAsync(Guid userId, Guid roleId)
        {
            // 检查用户和角色是否存在
            var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
            var role = await _roleRepo.GetByIdAsync(roleId) ?? throw new Exception("角色不存在");

            // 直接删除中间表
            var sql = "DELETE FROM \"AppRoleAppUser\" WHERE \"UsersId\" = @UserId AND \"RolesId\" = @RoleId;";
            await _dbConnection.ExecuteAsync(sql, new { UserId = userId, RoleId = roleId });
        }

        public async Task<List<AppRole>> GetUserRolesAsync(Guid userId)
        {
            var sql = "SELECT r.* FROM \"AppRole\" r " +
                      "INNER JOIN \"AppRoleAppUser\" aru ON r.\"Id\" = aru.\"RolesId\" " +
                      "WHERE aru.\"UsersId\" = @UserId AND r.\"IsDeleted\" = false";
            var roles = (await _dbConnection.QueryAsync<AppRole>(sql, new { UserId = userId })).ToList();
            return roles;
        }

        public async Task ChangePasswordAsync(Guid userId, string oldPwd, string newPwd)
        {
            var user = await _userRepo.GetByIdAsync(userId);
            if (user == null)
                throw new NotFoundException("用户不存在");

            var oldHash = HashPassword(oldPwd, user.Salt);
            if (user.PassWord != oldHash)
                throw new Exception("原密码错误");

            user.PassWord = HashPassword(newPwd, user.Salt);
            await _userRepo.UpdateAsync(user);
        }

        public async Task UpdateContactInfoAsync(Guid userId, string phone, string email)
        {
            var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
            user.Phone = phone;
            user.Email = email;
            await _userRepo.UpdateAsync(user);
        }

        public async Task<ContactInfoDto> GetContactInfoAsync(Guid userId)
        {
            var user = await _userRepo.GetByIdAsync(userId) ?? throw new Exception("用户不存在");
            return new ContactInfoDto
            {
                UserId = user.Id,
                Phone = user.Phone,
                Email = user.Email
            };
        }

        private string HashPassword(string pwd, string salt)
        {
            using var sha256 = System.Security.Cryptography.SHA256.Create();
            var bytes = System.Text.Encoding.UTF8.GetBytes(pwd + salt);
            var hash = sha256.ComputeHash(bytes);
            return Convert.ToBase64String(hash);
        }
    }

    public class NotFoundException : Exception
    {
        public NotFoundException(string message) : base(message) { }
    }
} 